Merge "rdbms: make LBFactory close/rollback dangling handles like LoadBalancer"
[lhc/web/wiklou.git] / tests / phpunit / includes / actions / WatchActionTest.php
1 <?php
2
3 /**
4 * @covers WatchAction
5 *
6 * @group Action
7 */
8 class WatchActionTest extends MediaWikiTestCase {
9
10 /**
11 * @var WatchAction
12 */
13 private $watchAction;
14
15 /**
16 * @var WikiPage
17 */
18 private $testWikiPage;
19
20 protected function setUp() {
21 parent::setUp();
22
23 $testTitle = Title::newFromText( 'UTTest' );
24 $this->testWikiPage = new WikiPage( $testTitle );
25 $testContext = new DerivativeContext( RequestContext::getMain() );
26 $testContext->setTitle( $testTitle );
27 $this->watchAction = new WatchAction( $this->testWikiPage, $testContext );
28 }
29
30 /**
31 * @throws MWException
32 */
33 protected function tearDown() {
34 parent::tearDown();
35
36 Hooks::clear( 'WatchArticle' );
37 Hooks::clear( 'UnwatchArticle' );
38 }
39
40 /**
41 * @covers WatchAction::getName()
42 */
43 public function testGetName() {
44 $this->assertEquals( 'watch', $this->watchAction->getName() );
45 }
46
47 /**
48 * @covers WatchAction::requiresUnblock()
49 */
50 public function testRequiresUnlock() {
51 $this->assertFalse( $this->watchAction->requiresUnblock() );
52 }
53
54 /**
55 * @covers WatchAction::doesWrites()
56 */
57 public function testDoesWrites() {
58 $this->assertTrue( $this->watchAction->doesWrites() );
59 }
60
61 /**
62 * @covers WatchAction::onSubmit()
63 * @covers WatchAction::doWatch()
64 */
65 public function testOnSubmit() {
66 /** @var Status $actual */
67 $actual = $this->watchAction->onSubmit( [] );
68
69 $this->assertTrue( $actual->isGood() );
70 }
71
72 /**
73 * @covers WatchAction::onSubmit()
74 * @covers WatchAction::doWatch()
75 */
76 public function testOnSubmitHookAborted() {
77 Hooks::register( 'WatchArticle', function () {
78 return false;
79 } );
80
81 /** @var Status $actual */
82 $actual = $this->watchAction->onSubmit( [] );
83
84 $this->assertInstanceOf( Status::class, $actual );
85 $this->assertTrue( $actual->hasMessage( 'hookaborted' ) );
86 }
87
88 /**
89 * @covers WatchAction::checkCanExecute()
90 */
91 public function testShowUserNotLoggedIn() {
92 $notLoggedInUser = new User();
93 $testContext = new DerivativeContext( $this->watchAction->getContext() );
94 $testContext->setUser( $notLoggedInUser );
95 $watchAction = new WatchAction( $this->testWikiPage, $testContext );
96 $this->setExpectedException( UserNotLoggedIn::class );
97
98 $watchAction->show();
99 }
100
101 /**
102 * @covers WatchAction::checkCanExecute()
103 */
104 public function testShowUserLoggedInNoException() {
105 $loggedInUser = $this->getMock( User::class );
106 $loggedInUser->method( 'isLoggedIn' )->willReturn( true );
107 $testContext = new DerivativeContext( $this->watchAction->getContext() );
108 $testContext->setUser( $loggedInUser );
109 $watchAction = new WatchAction( $this->testWikiPage, $testContext );
110
111 $exception = null;
112 try {
113 $watchAction->show();
114 } catch ( UserNotLoggedIn $e ) {
115 $exception = $e;
116 }
117 $this->assertNull( $exception,
118 'UserNotLoggedIn exception should not be thrown if user is logged in.' );
119 }
120
121 /**
122 * @covers WatchAction::onSuccess()
123 */
124 public function testOnSuccessMainNamespaceTitle() {
125 $testContext = $this->getMock(
126 DerivativeContext::class,
127 [ 'msg' ],
128 [ $this->watchAction->getContext() ]
129 );
130 $testOutput = new OutputPage( $testContext );
131 $testContext->setOutput( $testOutput );
132 $testContext->method( 'msg' )->willReturnCallback( function ( $msgKey ) {
133 return new RawMessage( $msgKey );
134 } );
135 $watchAction = new WatchAction( $this->testWikiPage, $testContext );
136
137 $watchAction->onSuccess();
138
139 $this->assertEquals( '<p>addedwatchtext
140 </p>', $testOutput->getHTML() );
141 }
142
143 /**
144 * @covers WatchAction::onSuccess()
145 */
146 public function testOnSuccessTalkPage() {
147 $testContext = $this->getMock(
148 DerivativeContext::class,
149 [],
150 [ $this->watchAction->getContext() ]
151 );
152 $testOutput = new OutputPage( $testContext );
153 $testContext->method( 'getOutput' )->willReturn( $testOutput );
154 $testContext->method( 'msg' )->willReturnCallback( function ( $msgKey ) {
155 return new RawMessage( $msgKey );
156 } );
157 $talkPageTitle = Title::newFromText( 'Talk:UTTest' );
158 $testContext->setTitle( $talkPageTitle );
159 $watchAction = new WatchAction( new WikiPage( $talkPageTitle ), $testContext );
160
161 $watchAction->onSuccess();
162
163 $this->assertEquals( '<p>addedwatchtext-talk
164 </p>', $testOutput->getHTML() );
165 }
166
167 /**
168 * @covers WatchAction::doWatch()
169 * @throws Exception
170 */
171 public function testDoWatchNoCheckRights() {
172 $notPermittedUser = $this->getUser( null, null, [] );
173 $actual = WatchAction::doWatch( $this->testWikiPage->getTitle(), $notPermittedUser, false );
174 $this->assertTrue( $actual->isGood() );
175 }
176
177 /**
178 * @covers WatchAction::doWatch()
179 * @throws Exception
180 */
181 public function testDoWatchUserNotPermittedStatusNotGood() {
182 $notPermittedUser = $this->getUser( null, null, [] );
183 $actual = WatchAction::doWatch( $this->testWikiPage->getTitle(), $notPermittedUser, true );
184 $this->assertFalse( $actual->isGood() );
185 }
186
187 /**
188 * @covers WatchAction::doWatch()
189 * @throws Exception
190 */
191 public function testDoWatchCallsUserAddWatch() {
192 $permittedUser = $this->getUser( null, null, [ 'editmywatchlist' ] );
193 $permittedUser->expects( $this->once() )
194 ->method( 'addWatch' )
195 ->with( $this->equalTo( $this->testWikiPage->getTitle() ), $this->equalTo( true ) );
196
197 $actual = WatchAction::doWatch( $this->testWikiPage->getTitle(), $permittedUser );
198
199 $this->assertTrue( $actual->isGood() );
200 }
201
202 /**
203 * @covers WatchAction::doUnWatch()
204 * @throws Exception
205 */
206 public function testDoUnWatchWithoutRights() {
207 $notPermittedUser = $this->getUser( null, null, [] );
208 $actual = WatchAction::doUnWatch( $this->testWikiPage->getTitle(), $notPermittedUser );
209
210 $this->assertFalse( $actual->isGood() );
211 }
212
213 /**
214 * @covers WatchAction::doUnWatch()
215 */
216 public function testDoUnWatchUserHookAborted() {
217 $permittedUser = $this->getUser( null, null, [ 'editmywatchlist' ] );
218 Hooks::register( 'UnwatchArticle', function () {
219 return false;
220 } );
221
222 $status = WatchAction::doUnWatch( $this->testWikiPage->getTitle(), $permittedUser );
223
224 $this->assertFalse( $status->isGood() );
225 $errors = $status->getErrors();
226 $this->assertEquals( 1, count( $errors ) );
227 $this->assertEquals( 'hookaborted', $errors[0]['message'] );
228 }
229
230 /**
231 * @covers WatchAction::doUnWatch()
232 * @throws Exception
233 */
234 public function testDoUnWatchCallsUserRemoveWatch() {
235 $permittedUser = $this->getUser( null, null, [ 'editmywatchlist' ] );
236 $permittedUser->expects( $this->once() )
237 ->method( 'removeWatch' )
238 ->with( $this->equalTo( $this->testWikiPage->getTitle() ) );
239
240 $actual = WatchAction::doUnWatch( $this->testWikiPage->getTitle(), $permittedUser );
241
242 $this->assertTrue( $actual->isGood() );
243 }
244
245 /**
246 * @covers WatchAction::getWatchToken()
247 * @throws Exception
248 */
249 public function testGetWatchTokenNormalizesToWatch() {
250 $user = $this->getUser( null, null );
251 $user->expects( $this->once() )
252 ->method( 'getEditToken' )
253 ->with( $this->equalTo( 'watch' ) );
254
255 WatchAction::getWatchToken( $this->watchAction->getTitle(), $user, 'INVALID_ACTION' );
256 }
257
258 /**
259 * @covers WatchAction::getWatchToken()
260 * @throws Exception
261 */
262 public function testGetWatchTokenProxiesUserGetEditToken() {
263 $user = $this->getUser( null, null );
264 $user->expects( $this->once() )->method( 'getEditToken' );
265
266 WatchAction::getWatchToken( $this->watchAction->getTitle(), $user );
267 }
268
269 /**
270 * @covers WatchAction::doWatchOrUnwatch()
271 * @throws Exception
272 */
273 public function testDoWatchOrUnwatchUserNotLoggedIn() {
274 $user = $this->getUser( false );
275 $user->expects( $this->never() )->method( 'removeWatch' );
276 $user->expects( $this->never() )->method( 'addWatch' );
277
278 $status = WatchAction::doWatchOrUnwatch( true, $this->watchAction->getTitle(), $user );
279
280 $this->assertTrue( $status->isGood() );
281 }
282
283 /**
284 * @covers WatchAction::doWatchOrUnwatch()
285 * @throws Exception
286 */
287 public function testDoWatchOrUnwatchSkipsIfAlreadyWatched() {
288 $user = $this->getUser();
289 $user->expects( $this->never() )->method( 'removeWatch' );
290 $user->expects( $this->never() )->method( 'addWatch' );
291
292 $status = WatchAction::doWatchOrUnwatch( true, $this->watchAction->getTitle(), $user );
293
294 $this->assertTrue( $status->isGood() );
295 }
296
297 /**
298 * @covers WatchAction::doWatchOrUnwatch()
299 * @throws Exception
300 */
301 public function testDoWatchOrUnwatchSkipsIfAlreadyUnWatched() {
302 $user = $this->getUser( true, false );
303 $user->expects( $this->never() )->method( 'removeWatch' );
304 $user->expects( $this->never() )->method( 'addWatch' );
305
306 $status = WatchAction::doWatchOrUnwatch( false, $this->watchAction->getTitle(), $user );
307
308 $this->assertTrue( $status->isGood() );
309 }
310
311 /**
312 * @covers WatchAction::doWatchOrUnwatch()
313 * @throws Exception
314 */
315 public function testDoWatchOrUnwatchWatchesIfWatch() {
316 $user = $this->getUser( true, false );
317 $user->expects( $this->never() )->method( 'removeWatch' );
318 $user->expects( $this->once() )
319 ->method( 'addWatch' )
320 ->with( $this->equalTo( $this->testWikiPage->getTitle() ), $this->equalTo( false ) );
321
322 $status = WatchAction::doWatchOrUnwatch( true, $this->watchAction->getTitle(), $user );
323
324 $this->assertTrue( $status->isGood() );
325 }
326
327 /**
328 * @covers WatchAction::doWatchOrUnwatch()
329 * @throws Exception
330 */
331 public function testDoWatchOrUnwatchUnwatchesIfUnwatch() {
332 $user = $this->getUser( true, true, [ 'editmywatchlist' ] );
333 $user->expects( $this->never() )->method( 'addWatch' );
334 $user->expects( $this->once() )
335 ->method( 'removeWatch' )
336 ->with( $this->equalTo( $this->testWikiPage->getTitle() ) );
337
338 $status = WatchAction::doWatchOrUnwatch( false, $this->watchAction->getTitle(), $user );
339
340 $this->assertTrue( $status->isGood() );
341 }
342
343 /**
344 * @param bool $isLoggedIn Whether the user should be "marked" as logged in
345 * @param bool $isWatched The value any call to isWatched should return
346 * @param array $permissions The permissions of the user
347 * @return PHPUnit_Framework_MockObject_MockObject
348 * @throws Exception
349 */
350 private function getUser(
351 $isLoggedIn = true,
352 $isWatched = true,
353 $permissions = []
354 ) {
355 $user = $this->getMock( User::class );
356 $user->method( 'getId' )->willReturn( 42 );
357 $user->method( 'isLoggedIn' )->willReturn( $isLoggedIn );
358 $user->method( 'isWatched' )->willReturn( $isWatched );
359 $this->overrideUserPermissions( $user, $permissions );
360 return $user;
361 }
362
363 }